<#assign object = doc.object>
package ${object.package}.service.base;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;
import java.util.Set;
import java.util.HashSet;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import redora.api.BusinessRuleViolation;
import redora.api.fetch.*;
import redora.exceptions.PersistenceException;
import ${object.package}.model.${object.name};
import ${object.package}.service.*;
import redora.util.BusinessRuleJSON;
<#if doc["//enum[@scope='global']"][0]??>
import ${object.package}.model.enums.*;
</#if>

/**
* This servlet dispatches standard retrieve / insert / update and delete operations on the ${object.name} object.
* This class is extended by ${object.name}Servlet, so if you want to modify the behavior of this class, please change that file.
* @see ${object.package}.service.http.${object.name}Servlet;
*/
public class ${object.name}ServletBase extends HttpServlet {
  	private final Logger l = Logger.getLogger("${object.package}.service.base.${object.name}ServletBase");
  	protected ${object.name}ServiceJSON serviceJSON;
  	protected ${object.name}Service service;

	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		PrintWriter out = resp.getWriter();
		resp.setContentType("text/html");
		try {
			Page page;
			if (req.getParameter("page") != null) {
				page = Page.fromJSON(req.getParameter("page"));
			} else {
				if(Scope.List.name().equalsIgnoreCase(req.getParameter("fetchScope")))
					page = Page.ALL_LIST;
				else if (Scope.Table.name().equalsIgnoreCase(req.getParameter("fetchScope")))
					page = Page.ALL_TABLE;
				else if (Scope.Form.name().equalsIgnoreCase(req.getParameter("fetchScope")))
					page = Page.ALL_FORM;
				else
					page = null;
			}
			if (req.getParameter("_operationType").equalsIgnoreCase("fetch")) {
				Map params = req.getParameterMap();
				if("true".equalsIgnoreCase(req.getParameter("findByParams")))
					serviceJSON.findByParams(params, page, out);
				else
					serviceJSON.findAll(page, out);	
			}
			if (req.getParameter("_operationType").equalsIgnoreCase("findById")) {
				serviceJSON.findById(Long.valueOf(req.getParameter("id")), page.getScope(), out);
			}
			<#list doc["/object/attributes/*[@finder='true']"] as att>
			if (req.getParameter("_operationType").equalsIgnoreCase("findBy${att.@fieldName?cap_first}")) {
				<#if att?node_name == "long">
				serviceJSON.findBy${att.@fieldName?cap_first}(Long.valueOf(req.getParameter("${att.@fieldName}")), page, out);
				<#elseif att?node_name == "integer">
				serviceJSON.findBy${att.@fieldName?cap_first}(Integer.parseInt(req.getParameter("${att.@fieldName}")), page, out);
				<#elseif att?node_name == "string">
				serviceJSON.findBy${att.@fieldName?cap_first}(req.getParameter("${att.@fieldName}"), page, out);
				<#elseif att?node_name == "date">
				;
				// findBy${att.@name?cap_first}(params.get("${att.@fieldName}")[0], page, out);
				<#elseif att?node_name == "boolean">
				serviceJSON.findBy${att.@fieldName?cap_first}(Boolean.valueOf(req.getParameter("${att.@fieldName}")), page, out);
				<#elseif att?node_name == "double">
				serviceJSON.findBy${att.@fieldName?cap_first}(Double.valueOf(req.getParameter("${att.@fieldName}")), page, out);
				</#if>
			} 
			</#list>
			<#list object.attributes.enum as att>
			if (req.getParameter("_operationType").equalsIgnoreCase("findBy${att.@fieldName?cap_first}")) {
				serviceJSON.findBy${att.@fieldName?cap_first}(<#if att.@scope == "local">${object.name}.</#if>${att.@className}.valueOfNullSafe(req.getParameter("${att.@fieldName}")), page, out);
			}
			</#list>
			<#list doc["/object/attributes/set[@multiplicity='n-to-m']"] as att>
			if (req.getParameter("_operationType").equalsIgnoreCase("findBy${att.@theirKey?cap_first}")) {
				serviceJSON.findBy${att.@theirKey?cap_first}(Long.valueOf(req.getParameter("${att.@theirKey}")), page, out);
			}
			if (req.getParameter("_operationType").equalsIgnoreCase("connectTo${att.@class?cap_first}")) {
				String ${att.@myKey}s[] = req.getParameter("${att.@myKey}").split(",");
				for (String ${att.@myKey} : ${att.@myKey}s) {
					String ${att.@theirKey}s[] = req.getParameter("${att.@theirKey}").split(",");
					for (String ${att.@theirKey} : ${att.@theirKey}s) {
                    	service.connectTo${att.@class}(Long.valueOf(${att.@myKey}), Long.valueOf(${att.@theirKey}), false);
                	}
                }
				out.print('{');
				out.print("response:");
				out.print('{');
				out.print("status:0");
				out.print('}');
				out.print('}');
			}
			if (req.getParameter("_operationType").equalsIgnoreCase("deleteRelationWith${att.@class}")) {
				String ${att.@myKey}s[] = req.getParameter("${att.@myKey}").split(",");
				for (String ${att.@myKey} : ${att.@myKey}s) {
					String ${att.@theirKey}s[] = req.getParameter("${att.@theirKey}").split(",");
					for (String ${att.@theirKey} : ${att.@theirKey}s) {
                    	service.deleteRelationWith${att.@class}(Long.valueOf(${att.@myKey}), Long.valueOf(${att.@theirKey}), false);
                	}
                }
				out.print('{');
				out.print("response:");
				out.print('{');
				out.print("status:0");
				out.print('}');
				out.print('}');
			}
			</#list>
			<#list object.attributes?children as att>
    			<#if (att?node_name == "long" && att.@name?ends_with("Id"))>
    		if (req.getParameter("_operationType").equalsIgnoreCase("findBy${att.@fieldName?cap_first}")) {
				serviceJSON.findBy${att.@fieldName?cap_first}(Long.valueOf(req.getParameter("${att.@fieldName}")), page, out);
			}
				</#if>
			</#list>
			if (req.getParameter("_operationType").equalsIgnoreCase("persist")) {
				${object.name} ${object.name?uncap_first} = serviceJSON.fromJson(${object.name}Util.getJSONValue(req));
				Set<BusinessRuleViolation> ret = service.persist(${object.name?uncap_first});
				if (ret.isEmpty()) {
					out.print('{');
					out.print("response:");
					out.print('{');
					out.print("status:0,data:");
					${object.name}Util.copy(${object.name?uncap_first}, resp.getWriter());
					out.print('}');
					out.print('}');
				} else {
					out.print('{');
					out.print("response:");
					out.print('{');
					out.print("status:-1,error:");
					BusinessRuleJSON.copy(ret, out);
					out.print('}');
					out.print('}');
				}
			} 
			if (req.getParameter("_operationType").equalsIgnoreCase("remove")) {
				out.print('{');
				out.print("response:");
				out.print('{');
				Set<BusinessRuleViolation> ret = new HashSet<BusinessRuleViolation>();
				String ids[] = req.getParameter("id").split(",");
				for (String id : ids) {
                    ${object.name} ${object.name?uncap_first} = service.findById(Long.valueOf(id), Scope.List);
                    ret.addAll(service.delete(${object.name?uncap_first}));
                }
				if (!ret.isEmpty()) {
					out.print("status:-1,error:");
					BusinessRuleJSON.copy(ret, out);
				} else {
					out.print("status:0");
				}
				out.print('}');
				out.print('}');
			} 
				<#if object.trashcan == "true">
			if (req.getParameter("_operationType").equalsIgnoreCase("trash")) {
				out.print('{');
                out.print("response:");
                out.print('{');
                Set<BusinessRuleViolation> ret = new HashSet<BusinessRuleViolation>();
                String ids[] = req.getParameter("id").split(",");
                for (String id : ids) {
                    ${object.name} ${object.name?uncap_first} = service.findById(Long.valueOf(id), Scope.List);
                    ret.addAll(service.trash(null, ${object.name?uncap_first}));
                }
                // Address address = serviceJSON.fromJson(AddressUtil.getJSONValue(req));
                if (!ret.isEmpty()) {
                    out.print("status:-1,error:");
                    BusinessRuleJSON.copy(ret, out);
                } else {
                    out.print("status:0");
                }
                out.print('}');
				out.print('}');
			} 
			if (req.getParameter("_operationType").equalsIgnoreCase("undo")) {
				String ids[] = req.getParameter("id").split(",");
                for (String id : ids) {
                    service.undo(Long.valueOf(id));
                }
				out.print('{');
				out.print("response:");
				out.print('{');
				out.print("status:0");
				out.print('}');
				out.print('}');
			} 
				</#if>
				<#if object.lazyScope[0]??>
			if (req.getParameter("_operationType").equalsIgnoreCase("fetchLazy")) {
				long id = Long.valueOf(req.getParameter("id"));
				serviceJSON.fetchLazy(id, out);
			}
				</#if>
			if (req.getParameter("_operationType").equalsIgnoreCase("dropTable")) {
				${object.name}TableUpdate tableUpdate = new ${object.name}TableUpdate();
				tableUpdate.drop();
			}
			out.flush();
		} catch (Exception e) {
		    resp.resetBuffer();
			out.print('{');
			out.print("response:");
			out.print('{');
			out.print("status:-2,error:");
			out.print("\"");
			out.print(
					"I failed to process a JSON request: "
							+ req.getParameter("_operationType") + ". Reason: " + e.getMessage());
			out.print("\"");
			out.print('}');
			out.print('}');
			out.flush();
			l.log(Level.SEVERE, "I failed to process a JSON request: " + req.getParameter("_operationType"), e);
			throw new ServletException("I failed to process a JSON request: " + req.getParameter("_operationType"), e);
		}
	}
	
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		doGet(req, resp);
	}

	@Override
	public void init() throws ServletException {
	  try {
	    serviceJSON = ServiceFactory.${object.name?uncap_first}ServiceJSON();
	    service = ServiceFactory.${object.name?uncap_first}Service();
	  } catch (PersistenceException e) {
	    l.log(Level.SEVERE, "Failed to initialize", e);
	  }
	  super.init();
	}
}
